﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="MatchRoundForm.cs" company="Roman '4ux-nbIx' Novitsky">
//   Copyright (c) Roman '4ux-nbIx' Novitsky 2010
// </copyright>
// <summary>
//   Defines the MatchRoundForm type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace MtgMC
{
    #region Namespace Imports

    using System;
    using System.ComponentModel;
    using System.Drawing;
    using System.Globalization;
    using System.Windows.Forms;

    using DataModel;

    using WindowsNative;

    #endregion


    /// <summary>
    /// Describes and manipulates the match round form.
    /// </summary>
    public partial class MatchRoundForm : Form
    {
        #region Constants and Fields

        private readonly MatchRound _matchRound = new MatchRound();
        private readonly Player _opponent;
        private readonly Player _player;
        private readonly int _roundNumber;
        private Size _size;

        #endregion


        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MatchRoundForm"/> class.
        /// </summary>
        /// <param name="player">
        /// The player.
        /// </param>
        /// <param name="opponent">
        /// The opponent.
        /// </param>
        /// <param name="roundNumber">
        /// The round number.
        /// </param>
        public MatchRoundForm(Player player, Player opponent, int roundNumber)
        {
            _player = player;
            _opponent = opponent;
            _roundNumber = roundNumber;

            InitializeComponent();

            DialogResult = DialogResult.Cancel;
            _nameLabel.Text = _player.Name + "'s health:";
            _opponentNameLabel.Text = _opponent.Name + "'s health:";
            _playerWinsMenuItem.Text = _player.Name + " Wins";
            _opponentWinsMenuItem.Text = _opponent.Name + " Wins";

            _health.ValueChanged += HealthValueChanged;
            _opponentHealth.ValueChanged += OpponentHealthValueChanged;

            UpdateHealthCounterColor(_health);
            UpdateHealthCounterColor(_opponentHealth);
            UpdateTitle();
        }

        #endregion


        #region Properties

        /// <summary>
        /// Gets a value indicating whether the ok button was clicked.
        /// </summary>
        /// <value>
        /// <c>True</c> if the ok button was clicked; otherwise, <c>false</c>.
        /// </value>
        public bool IsOkButtonClicked
        {
            get;
            private set;
        }


        /// <summary>
        /// Gets the round.
        /// </summary>
        /// <value>
        /// The round.
        /// </value>
        public MatchRound MatchRound
        {
            get
            {
                return _matchRound;
            }
        }

        #endregion


        #region Methods

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closed"/> event.
        /// </summary>
        /// <param name="e">
        /// The <see cref="T:System.EventArgs"/> that contains the event data.
        /// </param>
        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);

            BacklightNativeMethods.StopKeepingBacklightOn();
        }


        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"/> event.
        /// </summary>
        /// <param name="e">
        /// A <see cref="T:System.ComponentModel.CancelEventArgs"/> that contains the event data.
        /// </param>
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            if (DialogResult != DialogResult.Cancel)
            {
                return;
            }

            DialogResult result = MessageBox.Show(
                "Are you sure you want to abort the round?", 
                "Confirm Round Abort", 
                MessageBoxButtons.YesNo, 
                MessageBoxIcon.Question, 
                MessageBoxDefaultButton.Button2);

            if (result == DialogResult.Yes)
            {
                return;
            }

            e.Cancel = true;

            return;
        }


        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Load"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="T:System.EventArgs"/> that contains the event data.
        /// </param>
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            LayoutControls();

            _matchRound.StartTime = DateTime.Now;

            BacklightNativeMethods.StartKeepingBacklightOn();
        }


        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Resize"/> event.
        /// </summary>
        /// <param name="e">
        /// An <see cref="T:System.EventArgs"/> that contains the event data.
        /// </param>
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            LayoutControls();
        }


        private static DialogResult ConfirmRoundFinish(Player winner)
        {
            string text = string.Format(
                CultureInfo.CurrentCulture, "{0} wins!\nAre you sure you want to finish the round?", winner.Name);

            return MessageBox.Show(
                text, 
                "Round Finished", 
                MessageBoxButtons.OKCancel, 
                MessageBoxIcon.Question, 
                MessageBoxDefaultButton.Button2);
        }


        private static Color GetInterpolatedColor(Color from, Color to, int minValue, int maxValue, int currentValue)
        {
            int delta = maxValue - minValue;
            float percent = (maxValue - currentValue) / (delta / 100.0f);

            return GetInterpolatedColor(from, to, percent);
        }


        private static Color GetInterpolatedColor(Color from, Color to, float percent)
        {
            var r = (int)(from.R + (((to.R - from.R) / 100.0f) * percent));
            var g = (int)(from.G + (((to.G - from.G) / 100.0f) * percent));
            var b = (int)(from.B + (((to.B - from.B) / 100.0f) * percent));

            return Color.FromArgb(r, g, b);
        }


        private static void UpdateHealthCounterColor(UpDownSliderBase<int> healthCounter)
        {
            int currentValue = healthCounter.Value;
            Color color;

            if (currentValue > 20)
            {
                color = Color.Green;
            }
            else if (currentValue >= 13 && currentValue <= 20)
            {
                color = GetInterpolatedColor(Color.Green, Color.Yellow, 13, 20, currentValue);
            }
            else if (currentValue >= 2 && currentValue <= 12)
            {
                color = GetInterpolatedColor(Color.Yellow, Color.Red, 2, 12, currentValue);
            }
            else
            {
                color = Color.Red;
            }

            healthCounter.ForeColor = color;
        }


        private void AbortMenuItemClick(object sender, EventArgs e)
        {
            DialogResult = DialogResult.Cancel;
        }


        private void FinishRound(Player winner)
        {
            _matchRound.Winner = winner;
            _matchRound.Duration = DateTime.Now - _matchRound.StartTime;

            IsOkButtonClicked = true;

            DialogResult = DialogResult.OK;
        }


        private void HealthValueChanged(object sender, UpDownSliderEventArgs<int> e)
        {
            UpdateHealthCounterColor(_health);
        }


        private void LayoutControls()
        {
            if (_size.Width == Width && _size.Height == Height)
            {
                return;
            }

            _health.IsInitialized = false;
            _opponentHealth.IsInitialized = false;

            _size = new Size(Width, Height);

            SuspendLayout();

            int y = 0;

            // int height = (Height - (_nameLabel.Height * 2)) / 2;
            int height = Height / 2;

            _opponentNameLabel.Location = new Point(0, y);
            _opponentNameLabel.Width = Width;

            // y += _opponentNameLabel.Height;
            _opponentHealth.Location = new Point(0, y);
            _opponentHealth.Width = Width;
            _opponentHealth.Height = height;

            y += _opponentHealth.Height;
            _nameLabel.Location = new Point(0, y);
            _nameLabel.Width = Width;

            // y += _nameLabel.Height;
            _health.Location = new Point(0, y);
            _health.Width = Width;
            _health.Height = height;

            _health.IsInitialized = true;
            _opponentHealth.IsInitialized = true;

            ResumeLayout(true);
        }


        private void OnWinsMenuItemClick(Player winner)
        {
            DialogResult result = ConfirmRoundFinish(winner);

            if (result != DialogResult.OK)
            {
                return;
            }

            FinishRound(winner);
        }


        private void OpponentHealthValueChanged(object sender, UpDownSliderEventArgs<int> e)
        {
            UpdateHealthCounterColor(_opponentHealth);
        }


        private void OpponentWinsMenuItemClick(object sender, EventArgs e)
        {
            OnWinsMenuItemClick(_opponent);
        }


        private void PlayerWinsMenuItemClick(object sender, EventArgs e)
        {
            OnWinsMenuItemClick(_player);
        }


        private void UpdateTitle()
        {
            Text = string.Format(CultureInfo.CurrentCulture, "Round {0}", _roundNumber);
        }

        #endregion
    }
}